﻿using System;
using System.Diagnostics;
using Microsoft.Owin.Hosting;
using Hangfire;
using Hangfire.RecurringJobExtensions;
using Hangfire.Redis;
using Identification.Importer.Core;
using Serilog;
using Topshelf;

namespace Identification.Importer.Job
{
    public class ServiceComponent : ServiceControl
    {
        private IDisposable _app;
        private BackgroundJobServer _server;
        private readonly ServiceSetting _setting;

        public ServiceComponent(ServiceSetting setting)
        {
            _setting = setting;

            GlobalConfiguration.Configuration.UseSerilogLogProvider();
            GlobalConfiguration.Configuration.UseRedisStorage(_setting.RedisServer,
                new RedisStorageOptions
                {
                    Db = _setting.RedisDbIndex,
                    Prefix = _setting.RedisPrefix,
                    FetchTimeout = TimeSpan.FromSeconds(_setting.RedisFetchTimeoutSecond)
                });
        }

        private void ScheduleJob()
        {
            CronJob.AddOrUpdate(_setting.HangfireCronJobFile);
        }

        public bool Start(HostControl hostControl)
        {
            try
            {
                this.ScheduleJob();
                var option = new BackgroundJobServerOptions
                {
                    ServerName = Environment.MachineName,
                    HeartbeatInterval = TimeSpan.FromSeconds(30),
                    ServerCheckInterval = TimeSpan.FromSeconds(30),
                    Queues = _setting.HangfireServerQueues.ToArray()
                };
                _server = new BackgroundJobServer(option);

                _app = WebApp.Start<Startup>(_setting.HangfireServerUri);
                Log.Logger.Information($"hangfire server : {_setting.HangfireServerUri}");
                Log.Logger.Information("hangfire server running......");

                return true;
            }
            catch (Exception ex)
            {
                Log.Error(ex, "An exception occurred while starting service");
                return false;
            }
        }

        public bool Stop(HostControl hostControl)
        {
            try
            {
                _app.Dispose();
                _server.Dispose();
                foreach (ProcessThread thread in Process.GetCurrentProcess().Threads)
                {
                    thread.Dispose();
                }

                return true;
            }
            catch (Exception ex)
            {
                Log.Error(ex, "An exception occurred while stopping service");
                return false;
            }
        }
    }
}